package com.pignest.hotel.service;
  
import java.util.Date;
import java.util.List;

import com.pignest.framework.util.Utils;
import com.pignest.hotel.beans.AdjustAccountHistory;
import com.pignest.hotel.beans.Living;
import com.pignest.hotel.beans.Member;
import com.pignest.hotel.beans.Memberchargehistrory;
import com.pignest.hotel.beans.ProtocolUnit;
import com.pignest.hotel.beans.Room;
import com.pignest.hotel.beans.TbAccounts;
import com.pignest.hotel.beans.TbCloseAccounts;
import com.pignest.hotel.beans.TbGoods;
import com.pignest.hotel.beans.TbLiveGoodsBorrow;
import com.pignest.hotel.dao.InComeDao;
import com.pignest.hotel.dao.LivingDao;
import com.pignest.hotel.dao.RoomDao;
import com.pignest.hotel.definition.ChargeOpType;
import com.pignest.hotel.definition.InComeItemType;
import com.pignest.hotel.definition.LivingState;
import com.pignest.hotel.definition.PayMethod;
import com.pignest.hotel.definition.RoomLiveStatus;
import com.pignest.hotel.definition.RoomUseStatus;
import com.pignest.hotel.spring.Services;
import com.pignest.hotel.system.Hotel;
import com.pignest.hotel.ui.room.RoomHistogram;
import com.pignest.hotel.util.DateUtil;
import com.pignest.hotel.util.UIUtils;

public class IncomeService extends BaseService { 
	InComeDao  inComeDao;
	RoomDao roomDao;
	LivingDao livingDao;

	
	 
	public boolean addIncome() { 
		return true;
	}
	public InComeDao getInComeDao() {
		return inComeDao;
	}

	public void setInComeDao(InComeDao inComeDao) {
		this.inComeDao = inComeDao;
	}

    /**
     * 计算多个入住的消费
     * @param 多个入住
     * @param isPositive true 正数
     * */
    public int countAllConsumsUsed(List<Living> ls,boolean isPositive){
    	return inComeDao.countAllConsumsUsed(ls, isPositive);
    }
    
    /**计算单个所有入住消费
	 * 
	 * @param l 单个入住
	 * @param isPositive true 返回正数 false 反之
	 * @param isCheckOut true 包括已结账的，false 未结账的
	 * ***/
	public int countAllConsums(Living l,boolean isCheckOut,boolean  isPositive ){
		return inComeDao.countAllConsums(l,isCheckOut, isPositive);
	}
	 /**计算单个所有入住消费
	 * 
	 * @param l 多个入住
	 * @param isPositive true 返回正数 false 反之
	 * @param isCheckOut true 包括已结账的，false 未结账的
	 * ***/
	public int countAllConsums(List<Living> list,boolean isCheckOut,boolean  isPositive ){
		return inComeDao.countAllConsums(list, isCheckOut, isPositive);
	}
	/**计算多个所有消费
	 * @param ls 多个入住
	 ** @param state 入住状态
	 * @return 返回总消费的正数
	 * **/
	public int countAllConsumsByState(List<Living> ls,String state){
		return inComeDao.countAllConsumsByState(ls, state);
	}
	/**计算单个所有消费
	 * @param l 单个入住
	 * @param state 入住状态
	 * @return 返回总消费的正数
	 * ***/
	public int countAllConsumsByState(Living l,String state ){
		return inComeDao.countAllConsumsByState(l, state);
	}
	/**计算多个所有入住消费
	 * @param ls 多个入住
	 * @param isCheckOut true 包括已结账的，false 未结账的
	 * @param isPositive true 返回正数 false 反之
	 * **/
	
	public int countAllConsumsPayed(List<Living> ls,boolean isPositive){
		return inComeDao.countAllConsums( ls, true, isPositive);
	}
	/**计算总存款
     * @param ls多个入住
     * @param isCheckOut 是否结账 
     * 目前的业务没有对存款进行部分结账
     * ***/
	
	public int countAllStorages(List<Living> ls,boolean isCheckOut){
		return inComeDao.countAllStorages(ls,isCheckOut);
	}
	/**计算个人总存款
	 * @param living
	 * @param isCheckout true 已结账 false 未结账
	 * */
	public int countAllStroages(Living l,boolean isCheckOut){
		return inComeDao.countAllStroages(l, isCheckOut);
	}
	
	/**计算押金
	 * @param ls 多个入住
	 * @param isCheckOut 是否结账
	 * ***/
	public int countAllDeposit(List<Living> ls,boolean isCheckOut){
		return inComeDao.countAllDeposit(ls, isCheckOut);
	}
	/**计算押金
	 * @param l 单个入住
	 * @param isCheckOut 是否结账
	 * ***/
	public int countAllDeposit(Living l,boolean isCheckOut){
		return inComeDao.countAllDeposit(l, isCheckOut);
	}
	
	/**
	 * 查询已经结账的消费
	 * @param isPositive 是否为正数返回
	 */
	public int countPayed(Living l,boolean isPositive ){
		return inComeDao.countPayed(l, isPositive);
	}
	

	/**
	 * 查询多个房费
	 * 
	 * */
	public int countRoomConsums(List<Living> ls,boolean isPositive){
		return inComeDao.countRoomConsums(ls, isPositive);
	}
	
	 /**
     * 查询其它消费除了押金、房费、续存款、加收房费、房间调整费*/
    public int countOtherAccount(Living l,boolean isPositive){
    	return inComeDao.countOtherAccount(l, isPositive);
    }
    

	/**计算单个所有入住消费
     * @param living l
     * @param isPositive
     * ***/
    public int countAllConsumsUsed(Living l,boolean isPositive,Boolean isChecked){
    	return inComeDao.countAllConsumsUsed(l, isPositive,isChecked);
    }
    public int countRoomConsums(Living l,boolean isPositive)
    {
    	return inComeDao.countRoomConsums(l, isPositive);
    }
    /**
	 * 查询已结账的单个入住房费包括正常房费、调整费、加收房费
	 * 
	 * */
	public int countRoomConsumsChecked(Living l,boolean isPositive,List<TbAccounts> acc){
		return inComeDao.countRoomConsumsChecked(l, isPositive,acc);
	}
    public int countOtherConsums(Living l,boolean isPositive){
    	return inComeDao.countOtherAccount(l, isPositive);
    }
    /**
     * 按类型查询项目消费
     * type InComeItemType name值
     * */
    public int countTypeAccount(Living l,boolean isPositive,String type,Boolean isChecked,List<TbAccounts> acc){
    	return inComeDao.countTypeAccount(l, isPositive, type,isChecked,acc);
    }
    /**查询当前的多个入住的消费
     * 
     * */
    public int countCurCumsums(List<Living> ls){
    	return inComeDao.countCurCumsums(ls);
    }
    /**
     * 查询余额消费*/

    public int countBalance(Living l,boolean isPositive){
    	return inComeDao.countBalance(l, isPositive);
    }
	/**续存*/
	public Living updateComeOnAccount(TbAccounts ts,Living l)
	{
		this.insert(ts);
		l=UpdateLivingMoney(l);
		
	   Hotel.receive(ts.getPrice(), ChargeOpType.OnConsume, PayMethod.CASH,l.getRoom().getName()+"续存"+Utils.toPrice(ts.getPrice()));
		
		Services.getOtherBusiService().saveComeOnBill(l, ts.getPrice());
		return l;
	}
	/**调整*/
	public Living updateAdjustAccount(TbAccounts ts,Living l,AdjustAccountHistory ah)
	{
		this.update(ts);
		this.insert(ah);
		l=UpdateLivingMoney(l);
		return l;
	}
	/**查询调帐记录*/
	public List<AdjustAccountHistory> queryAdjustAccHis(String livingId,String accountId, String roomName, 
			String name,Date sAdjustTime,Date eAdjustTime,String adjustUser)
	{
		return inComeDao.queryAdjustHistory(livingId, accountId, roomName, name, sAdjustTime, eAdjustTime, adjustUser);
	}
	/**调整入住表相关的金额*/
	public Living UpdateLivingMoney(Living l)
	{
		int b=queryConsumption(l.getId());
		int storage =l.getStorage();
    	l.setUsed(storage-b);
    	l.setAvailable(b);
		this.update(l);
		return l;
	}
	/**计算当前入住余额,即要结算的金额
	 * 当前数据库值正数为客户充值负数为消费的
	 */
	public int queryConsumption(String LivingId)
	{
		return livingDao.queryConsumption(LivingId);
	}
	/**计算当前多入住余额,即要结算的金额
	 * 当前数据库值正数为客户充值负数为消费的
	 * sum()则为结算的金额
	 * **/
	public int queryAllConsum(List<Living> list){
		return livingDao.queryAllConsum(list);
	}

	/**
	 * 计算当前多入住消费金额
	 * 为正数
	 * */
	/*public int queryPositiveConsum(List<Living> list){
		return livingDao.queryPositiveConsum(list);
	}*/
	/**计算个人房间入住还有未结消费金额
	 * @param isPositive true 返回为正数 false 返回负数
	 * **/
	public int querySingleConsum(String livingId,boolean isPositive){
		return livingDao.querySingleConsum(livingId, isPositive);
	}
	/***根据多入住查询出账务未结记录**/
    public List<TbAccounts> queryAccoutsByMulLiving(List<Living> list)
    {
     return	inComeDao.queryAccoutsByMulLiving(list);
    }
    public List<TbAccounts> queryAccountsBySigleLiving(Living l){
    	return inComeDao.queryAccountBySingleLiving(l);
    }
    /**根据多入住查询统计账务记录
     * @param list 多入住记录
     * @param isCustorm true 则按客人统计false 则按消费项目统计 
     * */
    public List queryAccStaticByMulLiving(List<Living> list,boolean isCustorm){
    	return inComeDao.queryAccStaticByMulLiving(list, isCustorm);
    }
    /**根据多入住查询统计账务记录
     * @param list 多入住记录
     * @param type 1 按消费项目 2 则按客人统计 3 按房间 统计 
     * */
    public List queryAccStaticByMulLiving(List<Living> list,int type,String livingState){
    	return inComeDao.queryAccStaticByMulLiving(list, type,livingState);
    }
    /**根据多入住查询统计账务记录
     * @param list 单入住记录
     * @param type 1 按消费项目 2 则按客人统计 3 按房间 统计 
     * */
    public List queryAccStaticByLiving(String livingId,int type,String livingState){
    	return inComeDao.queryAccStaticByLiving(livingId, type,livingState);
    }
    /**
     * 根据多入住查询出入住、结账、挂账、部分结账状态的消费记录
     * */
    public List<TbAccounts> queryAllAccountUsedList(List<Living> list,String state){
    	return inComeDao.queryAllAccountUsedList(list, state);
    }
    public List<TbAccounts> queryAllAccountUsedList(String livingId,String state){
    	return inComeDao.queryAllAccountUsedList(livingId, state);
    }
    /**
	 * 根据物品的类别查询物品
	 * @param type '消费'、'借用'、 null 查询全部
	 * @author zhugb
	 * **/
    public List<TbGoods>queryGoods(String type){
    	return livingDao.queryGoods(type);
    }

    /**
     * 入住是否有未归还的记录
     * **/
    public List<TbLiveGoodsBorrow> isNoBorrow(List<Living> list){
    	return inComeDao.isNoBorrow(list);
    }
    /**入账
     * @param TbAccounts ac 入账
     * @param isConsume true 消费类  false 充值类
     * 如果是消费类则不必对入住总额进行更新
     * 如果是充值类则要对总额进行更新
     * */
    public Living inCome(TbAccounts ac,boolean isConsume,List<TbLiveGoodsBorrow> gb)
    {
    	this.insert(ac);
    	Living l =ac.getLiving();
    	if(!isConsume)
    	{
    		l.setStorage(l.getStorage()+ac.getPrice());
    		Hotel.receive(ac.getPrice(), ChargeOpType.OnConsume, PayMethod.CASH,"入账"+Utils.toPrice(ac.getPrice()));
    		
    	}
    	if(gb!=null)
    	{
    		for(TbLiveGoodsBorrow g:gb){
    			g.setBacktime(new Date());
    			this.update(g);
    		}
    	}
    	l=UpdateLivingMoney(l);
    	return l;
    	
    }
    /**部分结账*/
    public Living savePartCheckOut(Living l,TbCloseAccounts ca,List<TbAccounts> acc,Memberchargehistrory mch,TbAccounts account,int inCome)
    {
    	
        //续存款
    	int comeOn=0;
        if(account!=null){
        	this.insert(account);
        	comeOn =account.getPrice();
        	l.setStorage(l.getStorage()+comeOn);
        }
        l.setLiveState(LivingState.PARTCHECKOUT.name());
        
        if(ca!=null){
        	this.insert(ca);
        	l.setTbColoseAccounts(ca);

        }
        if(mch!=null){
    		this.insert(mch);
    		//更新会员总账
    		Member m=mch.getMember();
    		int b =Services.getMemberService().queryMemberBalance(m);
	    	m.setBalance(b);
	    	this.update(m);
    	}
        if(inCome>0&&mch==null){
           Hotel.receive(inCome, ChargeOpType.OnConsume, PayMethod.valueOf(ca.getType()),l.getRoom().getName()+LivingState.PARTCHECKOUT.getDisplayName()+":"+Utils.toPrice(inCome));
        }
        //改变结账状态为是
        for(TbAccounts a:acc){
        	a.setEndstate("是");
        	a.setEndtime(new Date());
        	this.update(a);
        }
        if(mch!=null)
		{
	    	this.insert(mch);
	    	Member m =mch.getMember();
	    	int b =Services.getMemberService().queryMemberBalance(m);
	    	m.setBalance(b);
	    	this.update(m);
		}
        UpdateLivingMoney(l);
        Services.getOtherBusiService().savePartCheckBill(l,acc,comeOn);
    	return l;
    }
    /**全部结账
     * @param List<Living> list多入住记录
     * @param TbCloseAccounts ca 结算账务
     * @param TbAccounts ac 加收账单 为空则不加收
     * @param Memberchargehistrory mch 会员消费 为空则不是会员消费
     * */
    public void saveAllCheck(List<Living> list,TbCloseAccounts ca,TbAccounts ac,Memberchargehistrory mch,int pay)
    {
    	//加收
    	if(ac!=null){
    		this.insert(ac);
    	}
    	//账单入库
    	if(ca!=null)
    		this.insert(ca);
    	if(mch!=null){
    		this.insert(mch);
    		//更新会员总账
    		Member m=mch.getMember();
    		int b =Services.getMemberService().queryMemberBalance(m);
	    	m.setBalance(b);
	    	this.update(m);
    	}
    	//查找当前入住的所有未结账单
    	List<TbAccounts> acc =this.queryAccoutsByMulLiving(list);
    	//更新账单
    	if(acc!=null){
    	 for(TbAccounts a:acc){
    		a.setAccountsId(ca.getId());
         	a.setEndstate("是");
         	a.setEndtime(new Date());
         	a.setOpUser(Hotel.getCurrentUser().getName());
         	this.update(a);
         }
    	}
    	 //更新入住状态
    	 for(Living ol:list){
    		 Living l =get(Living.class,ol.getId());
    		 l.setTbColoseAccounts(ca);
    		 l.setLiveState(LivingState.CHECKOUT.name());
    		 l.setLeaveDate(new Date());//设置离开时间
    		 l.setSerialNumber(ca.getSerialNumber());//设置与结账一致的序列号
    		 //每个入住的总额，消费、可用进行更新，此时账户消费项状态是"是"
    		// int consum=livingDao.queryCheckSingleConsum(l.getId(), true);
    		 int consum =countAllConsums(l,true,true);
    		 l.setStorage(consum);
    		 l.setUsed(consum);
    		 l.setAvailable(0);
    		 this.update(l);
    		 //更新房间状态
    		 Room room =l.getRoom();
    		 room.setLiveStatus(RoomLiveStatus.EMPTY.name());
     		 room.setUseStatus(RoomUseStatus.DIRTY.name());
     		 this.update(room);
     		 Services.getCustomService().insertCustomWhenCheckOut(l);
     		 Services.getOtherBusiService().saveCheckBill(l);
    	 }
    	 if(mch==null){
    		 Hotel.receive(-pay, ChargeOpType.OnConsume, PayMethod.valueOf(ca.getType()),LivingState.CHECKOUT.getDisplayName());
    	 }
    	
    }
    public void hangUp(List<Living> list,int add,String addName,ProtocolUnit unit,int backPrice)
    {
    	if(list==null)
    		return ;
    	for(Living l:list){
    		if(add!=0){
    			int iPrice =l.getAdjustPrice();
        		int iadd =iPrice*add/2;
        		TbAccounts ac = new TbAccounts();
        		   ac.setLiving(l);
                   ac.setType(InComeItemType.JSFF.name());
      			   ac.setCounts(1);
      			   ac.setPrice(-iadd);
      			   ac.setPrice2(iPrice);
      			   ac.setName(addName);
      			   ac.setEndstate("否");
      			   ac.setOpdate(DateUtil.toString(new Date(), "yyyy-MM-dd"));
      			   ac.setOptime(new Date());
      			   ac.setOpUser(Hotel.getCurrentUser().getName());
      			   ac.setRemark(addName+"共计:"+Utils.toPrice(iadd));
      			  this.insert(ac);
    		}
    		l.setLiveState(LivingState.HANDUP.name());
			l.setLeaveDate(new Date());
			l.setProtocolUnit(unit);
			UpdateLivingMoney(l);
	  		//更新房间状态
	    	Room room =l.getRoom();
	    	room.setLiveStatus(RoomLiveStatus.EMPTY.name());
	     	room.setUseStatus(RoomUseStatus.DIRTY.name());
	     	this.update(room);
	     	RoomHistogram rh = new RoomHistogram();
	     	rh.refreshRoom(room.getId());
	     	
	     	int price =countAllConsums(l,false,true);
	     	Services.getOtherBusiService().insertHangUp(l, unit, price);
	     	
	        Hotel.receive(-backPrice, ChargeOpType.OnConsume, PayMethod.CASH,room.getName()+"退回押金及续存款:"+Utils.toPrice(backPrice));
	     	
	     	//
    	}
    	
    }
    /**是否都未结过帐*/
	public boolean isCheckedOut(List<Living> list){
		list =queryBySelf(list);
		for(Living l:list){
			if(LivingState.valueOf(l.getLiveState()).name().equals(LivingState.CHECKOUT.name())){
				UIUtils.alert(l.getRoom().getName()+"已结账，请重新选择结账");
				return false;
			}
		}
		return true;
	}
	public float queryCheckOutDays(Living l,boolean isCheckOut,List<TbAccounts> acc)
	{
		return inComeDao.queryCheckOutDay(l,isCheckOut,acc);
	}
    /**查询自己的记录，相关于更新一下数据*/
    public List<Living> queryBySelf(List<Living> list)
    {
    	return inComeDao.queryBySelf(list);
    }
	public List<TbAccounts> queryConsume(Living l){
		return livingDao.queryAccountsNotDeposit(l);
	}
    public List<TbAccounts> queryAccountUsedList(List<Living> list,boolean isCheckOut)
    {
    	return inComeDao.queryAccountUsedList(list, isCheckOut);
    }
    /**查询单个已使用的消费*/
	public List<TbAccounts> queryAccountUsedList(String livingId,boolean isCheckOut){
		return inComeDao.queryAccountUsedList(livingId, isCheckOut);
	}
	public List<TbCloseAccounts> queryCloseAccNoPage( String username,
			 String type,  String orderNo,  String roomName,
			 String roomTypeId, Integer invoice, Date sDate,
			 Date eDate){
		return inComeDao.queryCloseAccNoPage(username, type, orderNo, roomName, roomTypeId, invoice, sDate, eDate);
	}
	public List<TbCloseAccounts> queryCloseAccPage( String username,
			 String type,  String orderNo,  String roomName,
			 String roomTypeId, Integer invoice, Date sDate,
			 Date eDate,  int start,final int length){
		return inComeDao.queryCloseAccPage(username, type, orderNo, roomName, roomTypeId, invoice, sDate, eDate, start, length);
	}
	public RoomDao getRoomDao() {
		return roomDao;
	}
	public void setRoomDao(RoomDao roomDao) {
		this.roomDao = roomDao;
	}
	public LivingDao getLivingDao() {
		return livingDao;
	}
	public void setLivingDao(LivingDao livingDao) {
		this.livingDao = livingDao;
	}
	 
}
